001 /* 002 * Copyright 2005 Niclas Hedhman 003 * Copyright 2005 Stephen J. McConnell. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 014 * implied. 015 * 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 package net.dpml.transit.link; 021 022 import net.dpml.util.StreamUtils; 023 024 import java.io.ByteArrayInputStream; 025 import java.io.ByteArrayOutputStream; 026 import java.io.IOException; 027 import java.io.InputStream; 028 import java.io.OutputStream; 029 import java.net.URI; 030 import java.net.URL; 031 import java.security.AccessController; 032 import java.security.PrivilegedActionException; 033 import java.security.PrivilegedExceptionAction; 034 035 import net.dpml.transit.Artifact; 036 import net.dpml.transit.NullArgumentException; 037 import net.dpml.transit.artifact.ArtifactNotFoundException; 038 import net.dpml.util.PropertyResolver; 039 040 /** 041 * A link manager that maintains persistent link information as a resource. 042 * Link resource located using the [cache]/[group]/[name]/[type]s/[name]-[version].[type].link 043 * resource naming convention. 044 * 045 * Applications should not call the methods for the LinkManager directly, 046 * and it is likely that the LinkManager remains outside the reachability of 047 * applications. 048 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 049 * @version 1.0.1 050 */ 051 public class ArtifactLinkManager 052 implements LinkManager 053 { 054 /** 055 * Sets the URI for the provided Link. 056 * The LinkManager is required to persist this information between 057 * JVM restarts and should be persisted on a scope larger than a 058 * single JVM, typically a host or a local area network. LinkManagers 059 * are encouraged to establish other virtual scopes independent of 060 * network topologies. 061 * 062 * @param linkUri the uri of the link resource 063 * @param targetUri the uri that the link redirects to 064 * @exception IOException if the mapping could not be updated. 065 */ 066 public void setTargetURI( final URI linkUri, final URI targetUri ) 067 throws IOException 068 { 069 if( null == linkUri ) 070 { 071 throw new NullArgumentException( "linkUri" ); 072 } 073 074 try 075 { 076 AccessController.doPrivileged( 077 new PrivilegedExceptionAction() 078 { 079 public Object run() 080 throws IOException 081 { 082 String artifact = linkUri.toASCIIString(); 083 URL store = new URL( null, artifact, new net.dpml.transit.artifact.Handler() ); 084 OutputStream out = store.openConnection().getOutputStream(); 085 byte[] array = getByteArray( targetUri ); 086 ByteArrayInputStream in = new ByteArrayInputStream( array ); 087 StreamUtils.copyStream( in, out, true ); 088 return null; // nothing to return 089 } 090 } 091 ); 092 } 093 catch( PrivilegedActionException e ) 094 { 095 throw (IOException) e.getException(); 096 } 097 } 098 099 /** 100 * Returns the URI that the provided link URI instance is pointing to. 101 * @param linkUri the link uri from which the target will be resolved 102 * @exception LinkNotFoundException if the supplied link uri could not be located 103 * @exception IOException if the mapping could not be retrieved, due to 104 * an IOException during link retrival. 105 * @return target URI that the link points to (possibly null if the link does 106 * not declare a target) 107 */ 108 public URI getTargetURI( final URI linkUri ) 109 throws IOException, LinkNotFoundException 110 { 111 try 112 { 113 URI result = (URI) AccessController.doPrivileged( 114 new PrivilegedExceptionAction() 115 { 116 public Object run() 117 throws IOException 118 { 119 URL store = null; 120 if( Artifact.isRecognized( linkUri ) ) 121 { 122 String artifact = linkUri.toASCIIString(); 123 store = new URL( null, artifact, new net.dpml.transit.artifact.Handler() ); 124 } 125 else 126 { 127 store = linkUri.toURL(); 128 } 129 130 ByteArrayOutputStream out = new ByteArrayOutputStream(); 131 InputStream in = store.openConnection().getInputStream(); 132 StreamUtils.copyStream( in, out, true ); 133 String target = out.toString( "ISO8859-1" ); 134 String path = PropertyResolver.resolve( target ); 135 URI value = URI.create( path ); 136 return value; 137 } 138 } 139 ); 140 return result; 141 } 142 catch( PrivilegedActionException e ) 143 { 144 Exception exception = e.getException(); 145 if( exception instanceof ArtifactNotFoundException ) 146 { 147 final String error = 148 "Link not found: " 149 + linkUri; 150 throw new LinkNotFoundException( error, linkUri ); 151 } 152 else 153 { 154 throw (IOException) exception; 155 } 156 } 157 } 158 159 private byte[] getByteArray( URI uri ) throws IOException 160 { 161 if( null != uri ) 162 { 163 return uri.toString().getBytes( "ISO8859-1" ); 164 } 165 else 166 { 167 return new byte[0]; 168 } 169 } 170 }